package com.lhz.framework.aspect.param;


import cn.hutool.core.convert.Convert;
import com.lhz.common.constant.DataScopeConstant;
import com.lhz.common.page.BaseQueryParam;
import com.lhz.common.utils.string.StrFormatter;
import com.lhz.framework.security.HolderInfoManager;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 操作日志记录处理
 *
 * @author LiHezZ
 */
@Aspect
@Component
public class DataScopeAspect {

    /**
     * 环绕通知，调用目标方法
     */
    @Before("@annotation(dataScopeAnnotation)")
    public void doBeforeAdvice(JoinPoint joinPoint, DataScope dataScopeAnnotation) {
        //获取目标方法的参数信息
        Object[] obj = joinPoint.getArgs();
        Integer dataScope = null;
        BaseQueryParam param = null;
        for (Object o : obj) {
            //对BaseQueryParam设置用户的数据权限信息
            if (o instanceof BaseQueryParam) {
                // 权限范围 - 1：全部数据 2：自定数据 3：本部门及以下数据 4：本部门数据  5:个人数据
                param = (BaseQueryParam) o;
                String userId = HolderInfoManager.getUserId();
                // 获取请求路径
                String servletPath = HolderInfoManager.getCurrentRequest().getServletPath();
                // 如果有角色菜单数据权限，则以菜单的为准
                dataScope = HolderInfoManager.getDataScope();
                param.setDataScope(dataScope);
                switch (dataScope) {
                    case 2:
                        List<Integer> deptIds = HolderInfoManager.getDeptIds();
                        param.setDeptIds(deptIds);
                        break;
                    case 3:
                    case 4:
                        param.setDeptId(HolderInfoManager.getDeptId());
                        break;
                    case 5:
                        param.setUserId(HolderInfoManager.getUserId());
                        break;
                    default:
                        break;
                }
                break;
            }
        }

        // sql处理
        if (dataScope != null && param != null) {
            dataScopeFilter(joinPoint, param, dataScope, dataScopeAnnotation.deptAlias(), dataScopeAnnotation.userAlias());
        }
    }

    public static void dataScopeFilter(JoinPoint joinPoint, BaseQueryParam param, Integer dataScope, String deptAlias, String userAlias) {
        StringBuilder sqlString = new StringBuilder();
        List<String> conditions = new ArrayList<>();

        if (DataScopeConstant.DIY.equals(dataScope)) {
            List<Integer> deptIds = param.getDeptIds();
            List<String> deptIdStrList = deptIds.stream().map(Convert::toStr).toList();
            String deteStr = String.join(",", deptIdStrList);
            if (StringUtils.isNotBlank(deptAlias)) {
                sqlString.append(format(" {}.id IN ( {} ) ", deptAlias, deteStr));
            } else if (StringUtils.isNotBlank(userAlias)) {
                sqlString.append(format(" {}.dept_id IN ( {} ) ", userAlias, deteStr));
            }
        } else if (DataScopeConstant.UNDER_DEPT.equals(dataScope)) {
            if (StringUtils.isBlank(deptAlias)) {
                throw new RuntimeException("deptAlias - 别名错误");
            }
            sqlString.append(format(" (find_in_set({},{}.ancestors) or {}.id = {} ) ", param.getDeptId(), deptAlias, deptAlias, param.getDeptId()));
        } else if (DataScopeConstant.DEPT.equals(dataScope)) {
            if (StringUtils.isNotBlank(deptAlias)) {
                sqlString.append(format(" {}.id = {} ", deptAlias, param.getDeptId()));
            } else if (StringUtils.isNotBlank(userAlias)) {
                sqlString.append(format(" {}.dept_id = {} ", userAlias, param.getDeptId()));
            }
        } else if (DataScopeConstant.PERSONAL.equals(dataScope)) {
            if (StringUtils.isBlank(userAlias)) {
                throw new RuntimeException("userAlias - 别名错误");
            }
            // userId为String类型，加上单引号
            sqlString.append(format(" {}.id = '{}' ", userAlias, param.getUserId()));
        }
        param.setDataScopeSql(" AND (" + sqlString + ")");
    }

    public static String format(String template, Object... params) {
        if (params == null || (StringUtils.isEmpty(template))) {
            return template;
        }
        return StrFormatter.format(template, params);
    }
}
